{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5f663c69",
   "metadata": {},
   "source": [
    "# Huggingface Endpoints\n",
    "\n",
    "Hugging Face Hub은 12만 개 이상의 모델, 2만 개의 데이터셋, 5만 개의 데모 앱(Spaces)을 보유한 플랫폼으로, 모두 오픈 소스이며 공개적으로 사용 가능합니다. 이 온라인 플랫폼에서 사람들은 쉽게 협업하고 함께 머신러닝을 구축할 수 있습니다.\n",
    "\n",
    "Hugging Face Hub은 또한 다양한 ML 애플리케이션을 구축하기 위한 다양한 엔드포인트를 제공합니다. 이 예제는 다양한 유형의 엔드포인트에 연결하는 방법을 보여줍니다.\n",
    "\n",
    "특히, 텍스트 생성 추론은 Text Generation Inference에 의해 구동됩니다. 이는 매우 빠른 텍스트 생성 추론을 위해 맞춤 제작된 Rust, Python, gRPC 서버입니다.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed7a0967",
   "metadata": {},
   "source": [
    "## 허깅페이스 토큰 발급\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d5addfb",
   "metadata": {},
   "source": [
    "허깅페이스(https://huggingface.co) 에 회원가입을 한 뒤, 아래의 주소에서 토큰 발급을 신청합니다.\n",
    "\n",
    "- 토큰 발급주소: https://huggingface.co/docs/hub/security-tokens\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ede30ac",
   "metadata": {},
   "source": [
    "## 참고 모델 리스트\n",
    "\n",
    "- 허깅페이스 LLM 리더보드: https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard\n",
    "- 모델 리스트: https://huggingface.co/models?pipeline_tag=text-generation&sort=downloads\n",
    "- LogicKor 리더보드: https://lk.instruct.kr/"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf342258",
   "metadata": {},
   "source": [
    "## Huggingface Endpoints 사용\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18380b00",
   "metadata": {},
   "source": [
    "사용하기 위해서는 Python의 `huggingface_hub` [패키지를 설치](https://huggingface.co/docs/huggingface_hub/installation)해야 합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed667993",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !pip install -qU huggingface_hub"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "793c830b",
   "metadata": {},
   "source": [
    "`.env` 파일에 이미 발급받은 토큰을 `HUGGINGFACEHUB_API_TOKEN` 을 저장한 뒤 다음 단계롤 진행합니다.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc8523a3",
   "metadata": {},
   "source": [
    "`HUGGINGFACEHUB_API_TOKEN` 을 불러옵니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24628822",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f06e9100",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LangSmith 추적을 설정합니다. https://smith.langchain.com\n",
    "# !pip install langchain-teddynote\n",
    "from langchain_teddynote import logging\n",
    "\n",
    "# 프로젝트 이름을 입력합니다.\n",
    "logging.langsmith(\"CH04-Models\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "265ccbbf",
   "metadata": {},
   "source": [
    "허깅페이스 토큰을 입력합니다"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from huggingface_hub import login\n",
    "\n",
    "login()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5302e153",
   "metadata": {},
   "source": [
    "간단한 프롬프트를 생성합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01e4a122",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "\n",
    "template = \"\"\"Question: {question}\n",
    "\n",
    "Answer:\"\"\"\n",
    "\n",
    "template = \"\"\"<|system|>\n",
    "You are a helpful assistant.<|end|>\n",
    "<|user|>\n",
    "{question}<|end|>\n",
    "<|assistant|>\"\"\"\n",
    "\n",
    "prompt = PromptTemplate.from_template(template)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a4fdc3b",
   "metadata": {},
   "source": [
    "## Serverless Endpoints\n",
    "\n",
    "Inference API 는 무료로 사용할 수 있으며 요금은 제한되어 있습니다. 프로덕션을 위한 추론 솔루션이 필요한 경우, [Inference Endpoints](https://huggingface.co/docs/inference-endpoints/index) 서비스를 확인하세요. Inference Endpoints 를 사용하면 모든 머신 러닝 모델을 전용 및 완전 관리형 인프라에 손쉽게 배포할 수 있습니다. 클라우드, 지역, 컴퓨팅 인스턴스, 자동 확장 범위 및 보안 수준을 선택하여 모델, 지연 시간, 처리량 및 규정 준수 요구 사항에 맞게 설정하세요.\n",
    "\n",
    "다음은 Inference API 에 액세스하는 방법의 예시입니다.\n",
    "\n",
    "**참고**\n",
    "\n",
    "- [Serverless Endpoints](https://huggingface.co/docs/api-inference/index)\n",
    "- [Inference Endpoints](https://huggingface.co/docs/inference-endpoints/index)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aad3ae86",
   "metadata": {},
   "source": [
    "`repo_id` 변수에 HuggingFace 모델의 `repo ID`(저장소 ID) 를 할당합니다.\n",
    "- `microsoft/Phi-3-mini-4k-instruct` 모델: https://huggingface.co/microsoft/Phi-3-mini-4k-instruct"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b5a7b7d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_huggingface import HuggingFaceEndpoint\n",
    "\n",
    "# 사용할 모델의 저장소 ID를 설정합니다.\n",
    "repo_id = \"microsoft/Phi-3-mini-4k-instruct\"\n",
    "\n",
    "llm = HuggingFaceEndpoint(\n",
    "    repo_id=repo_id,  # 모델 저장소 ID를 지정합니다.\n",
    "    max_new_tokens=256,  # 생성할 최대 토큰 길이를 설정합니다.\n",
    "    temperature=0.1,\n",
    "    task=\"text-generation\",\n",
    "    huggingfacehub_api_token=os.environ[\"HUGGINGFACEHUB_API_TOKEN\"],  # 허깅페이스 토큰\n",
    ")\n",
    "\n",
    "# LLMChain을 초기화하고 프롬프트와 언어 모델을 전달합니다.\n",
    "chain = prompt | llm | StrOutputParser()\n",
    "# 질문을 전달하여 LLMChain을 실행하고 결과를 출력합니다.\n",
    "response = chain.invoke({\"question\": \"what is the capital of South Korea?\"})\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7ed6ac6",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "410ba3d7",
   "metadata": {},
   "source": [
    "## 전용 엔드포인트(Dedicated Endpoint)\n",
    "\n",
    "무료 서버리스 API를 사용하면 솔루션을 빠르게 구현하고 반복할 수 있습니다. 하지만 로드가 다른 요청과 공유되기 때문에 대용량 사용 사례에서는 속도 제한이 있을 수 있습니다.\n",
    "\n",
    "엔터프라이즈 워크로드의 경우, [Inference Endpoints - Dedicated](https://huggingface.co/inference-endpoints/dedicated)를 사용하는 것이 가장 좋습니다. 이를 통해 더 많은 유연성과 속도를 제공하는 완전 관리형 인프라에 액세스할 수 있습니다.\n",
    "\n",
    "이러한 리소스에는 지속적인 지원과 가동 시간 보장은 물론 AutoScaling과 같은 옵션도 포함됩니다.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "118bf744",
   "metadata": {},
   "source": [
    "![](./images/hf-endpoint-1.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c5b0969",
   "metadata": {},
   "source": [
    "- `hf_endpoint_url` 변수에 Inference Endpoint의 URL을 설정합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26f30fc0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Inference Endpoint URL을 아래에 설정합니다.\n",
    "hf_endpoint_url = \"https://slcalzucia3n7y3g.us-east-1.aws.endpoints.huggingface.cloud\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14272123",
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = HuggingFaceEndpoint(\n",
    "    # 엔드포인트 URL을 설정합니다.\n",
    "    endpoint_url=hf_endpoint_url,\n",
    "    max_new_tokens=512,\n",
    "    temperature=0.01,\n",
    "    task=\"text-generation\",\n",
    ")\n",
    "\n",
    "# 주어진 프롬프트에 대해 언어 모델을 실행합니다.\n",
    "llm.invoke(input=\"대한민국의 수도는 어디인가요?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff9ef595",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"A chat between a curious user and an artificial intelligence assistant. \"\n",
    "            \"The assistant gives helpful, detailed, and polite answers to the user's questions.\",\n",
    "        ),\n",
    "        (\"user\", \"Human: {question}\\nAssistant: \"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "chain = prompt | llm | StrOutputParser()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "35a612a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "chain.invoke(\"대한민국의 수도는?\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
